package com.ruoyi.common.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.spring.SpringUtils;
import org.xbill.DNS.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.UnknownHostException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CommUtils {

    public static final String REQ_API_URI="https://ssl-server.yygzs.cn";
//    public static final String REQ_API_URI="http://tunnel-test01.yygzs.cn";
//    public static final String REQ_API_URI="http://127.0.0.1:8082";
    private static final String DOMAIN_REGEX =
            "^(\\*\\.)?[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?(?:\\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*(?:\\.[A-Za-z]{2,})$";

    public static AjaxResult isHasAuthInfo(String domain, String txtVal){
        try {
            // 创建 DNS 查询
            String dnsServer = "8.8.8.8"; // 使用 Google DNS，或替换为您的 DNS 服务器
            Lookup lookup = new Lookup(domain.trim(), Type.CNAME);
            lookup.setResolver(new SimpleResolver(dnsServer));
            lookup.setCache(null); // 不使用缓存
            lookup.run();
            Console.log("域名：{}，记录值：{}", domain, txtVal);
            if (lookup.getResult() == Lookup.SUCCESSFUL) {
                for (Record record : lookup.getAnswers()) {
                    CNAMERecord cnameRecord = (CNAMERecord) record;
                    System.out.println("CNAME for " + domain.trim() + " is: " + cnameRecord.getTarget());
                    if(cnameRecord.getTarget().toString().contains(txtVal.trim())){
                        return AjaxResult.success("", cnameRecord.getTarget().toString());
                    }
                }
            }else{
                System.out.println("CNAME for " + domain.trim() + " is: 查询失败！");
            }
        } catch (TextParseException | UnknownHostException e) {
            return AjaxResult.error("错误008！");
        }
        return AjaxResult.error("未查询到解析记录");
    }

    public static AjaxResult isHasAuthInfo1(String domain, String txtVal){
        try {
            // 创建 DNS 查询
            Lookup lookup = new Lookup(domain, Type.TXT);
            Record[] records = lookup.run();
            if (lookup.getResult() == Lookup.SUCCESSFUL && records != null) {
                for (Record record : records) {
                    TXTRecord txtRecord = (TXTRecord) record;
                    List<String> strings = txtRecord.getStrings();
                    Console.log(JSONUtil.toJsonStr(strings));
                    return AjaxResult.success();
                }
            } else {
                System.out.println("未找到 TXT 记录或出现错误: " + lookup.getErrorString());
            }
        } catch (TextParseException e) {
            System.err.println("错误："+e.getMessage());
        }
        return AjaxResult.error("错误！");
    }


    // 域名正则表达式
    public static boolean isValidDomain(String domain) {
        if (domain == null || domain.isEmpty()) {
            return false;
        }
        Pattern pattern = Pattern.compile(DOMAIN_REGEX);
        Matcher matcher = pattern.matcher(domain);
        return matcher.matches();
    }


    public static boolean isPrivateKey(String keyStr, String type) {
        try {
            byte[] decodedKey = Base64.getDecoder().decode(keyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey.getAlgorithm().equals(type);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 通过证书文件获取证书信息得方法
     */
    public static JSONObject getSSLInfoByFile(String filePath){
        try {
            JSONObject resultObj = new JSONObject();
            //获取到证书对象信息  域名，有效时间
            FileInputStream fis = new FileInputStream(filePath.replace("/profile/upload", ""));
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(fis);
            resultObj.set("startTime", DateUtil.format(cert.getNotBefore(), "YYYY-MM-dd HH:mm:ss"));
            resultObj.set("endTime", DateUtil.format(cert.getNotAfter(), "YYYY-MM-dd HH:mm:ss"));
            resultObj.set("domainTxt", cert.getSubjectX500Principal().getName().substring(cert.getSubjectX500Principal().getName().lastIndexOf("=")+1));
            // 注意：这里使用了非贪婪匹配(.*?)，并且处理了值可能被引号包围的情况
            String regex = "O=([^,]*)";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(cert.getIssuerDN().getName());
            if (matcher.find()) {
                resultObj.set("ca", matcher.group(1).trim().replaceAll("\"", ""));
            } else {
                resultObj.set("ca", "未查询到厂商");
            }
            resultObj.set("signTypeName", cert.getSigAlgName());
            fis.close();
            return resultObj;
        } catch (Exception e) {
            System.err.println("写入文件时出错: " + e.getMessage());
        }
        return null;
    }

    public static String getRequestBody(HttpServletRequest request){
        try {
            StringBuilder sb = new StringBuilder();
            try (BufferedReader reader = request.getReader()) {
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            }
            return sb.toString().trim();
        } catch (IOException e) {
            Console.error("获取请求参数异常");
        }
        return null;
    }

    /**
     * 获取客户端IP地址的方法
     * @param request HttpServletRequest对象
     * @return 客户端IP地址
     */
    public static String getClientIp(HttpServletRequest request) {
        String xfHeader = request.getHeader("X-Forwarded-For");
        String ip = "";
        if (xfHeader == null) {
            ip = request.getHeader("Proxy-Client-IP");
            if (ip == null || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } else {
            // 如果通过多个代理，第一个IP为客户端真实IP,多个IP值用逗号分隔
            if (xfHeader.contains(",")) {
                xfHeader = xfHeader.split(",")[0];
            }
            ip = xfHeader;
        }
        return ip;
    }

    public static String schemeDomain(HttpServletRequest request){
        // 获取请求的协议（http或https）
        String scheme = request.getScheme();
        String reqUri = request.getRequestURL().toString();
        // 获取请求的域名（不包括端口号）
        String serverName = request.getServerName();
        // 如果需要，也可以获取服务器端口号
        int serverPort = request.getServerPort();
        // 构建完整的URL（如果需要）
        String fullUrl = scheme + "://" + serverName;
        if (serverPort != 80 && serverPort != 443) { // 通常80是http的默认端口，443是https的默认端口
            fullUrl += ":" + serverPort;
        }
        Console.log("====================>",reqUri, scheme);
        return fullUrl;
    }

    public static void main(String[] args) {
        AjaxResult aj = isHasAuthInfo("_acme-challenge.ycdf91.cn", "");
        Console.log(JSONUtil.toJsonStr(aj));
        if(aj.isSuccess()){
            String CNAMEDomain = String.valueOf(aj.get("data"));
            aj = isHasAuthInfo1(CNAMEDomain.substring(0, CNAMEDomain.lastIndexOf(".")), "");
            Console.log(JSONUtil.toJsonStr(aj));
        }

    }
}
